package com.ruoyi.web.controller.activity;

import com.ruoyi.activity.dto.FlowApproveDto;
import com.ruoyi.activity.service.IFlowService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricTaskInstance;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.rmi.ServerException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipInputStream;

/**
 * 流程管理
 */
@Api(tags = {"部署管理接口"})
@Controller
@RequestMapping("/flow/manage")
public class FlowController extends BaseController {

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;
    @Resource
    protected HistoryService historyService;

    @Resource
    RepositoryService repositoryService;

    @Resource
    private IFlowService flowServiceImpl;

    @Resource
    ProcessEngineConfiguration configuration;

    private String prefix = "activiti/manage";

    @GetMapping("")
    public String processList()
    {
        return prefix + "/processList";
    }

    @GetMapping("deploy")
    public String deploy()
    {
        return prefix + "/deployProcess";
    }

    @GetMapping("suspend")
    public String suspend(@RequestParam("pdid") String pdid, ModelMap mmap)
    {
        mmap.put("pdid", pdid);
        return prefix + "/suspend";
    }

    @GetMapping("activate")
    public String activate(@RequestParam("pdid") String pdid, ModelMap mmap)
    {
        mmap.put("pdid", pdid);
        return prefix + "/activate";
    }

    //    @ApiOperation("上传一个工作流文件")
    @RequestMapping(value = "/uploadworkflow", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult fileupload(@RequestParam MultipartFile uploadfile) {
        try {
            String filename = uploadfile.getOriginalFilename();
            InputStream is = uploadfile.getInputStream();
            if (filename.endsWith("zip")) {
                repositoryService.createDeployment().name(filename).addZipInputStream(new ZipInputStream(is)).deploy();
            } else if (filename.endsWith("bpmn") || filename.endsWith("xml")) {
                repositoryService.createDeployment().name(filename).addInputStream(filename, is).deploy();
            } else {
                return AjaxResult.error("文件格式错误");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("部署失败");
        }
        return AjaxResult.success("部署成功");
    }

    //    @ApiOperation("查询已部署工作流列表")
    @RequestMapping(value = "/getprocesslists", method = RequestMethod.POST)
    @ResponseBody
    public TableDataInfo getlist(@RequestParam(required = false) String key, @RequestParam(required = false) String name,
                                 @RequestParam(required = false) Boolean latest, Integer pageSize, Integer pageNum) {
        return flowServiceImpl.getlist(key, name, latest, pageSize, pageNum);

    }

    //    @ApiOperation("删除一次部署的工作流")
    @RequestMapping(value = "/remove/{deploymentId}", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult remove(@PathVariable String deploymentId) {
        repositoryService.deleteDeployment(deploymentId, true);
        return AjaxResult.success();
    }


    //    @ApiOperation("查看工作流图片")
    @RequestMapping(value = "/showresource", method = RequestMethod.GET)
    public void showresource(@RequestParam("pdid") String pdid,
                             HttpServletResponse response) throws Exception {
        flowServiceImpl.showresource(pdid, response);
    }

    //    @ApiOperation("查看工作流定义")
    @RequestMapping(value = "/showProcessDefinition/{pdid}/{resource}", method = RequestMethod.GET)
    public void showProcessDefinition(@PathVariable("pdid") String pdid, @PathVariable(value="resource") String resource,
                                      HttpServletResponse response) throws Exception {
        InputStream is = repositoryService.getResourceAsStream(pdid, resource);
        ServletOutputStream output = response.getOutputStream();
        IOUtils.copy(is, output);
    }
//
//    @ApiOperation("将流程定义转为模型")
//    @RequestMapping(value = "/exchangeProcessToModel/{pdid}", method = RequestMethod.GET)
//    @ResponseBody
//    public String exchangeProcessToModel(@PathVariable("pdid") String pdid, HttpServletResponse response) throws Exception {
//        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().processDefinitionId(pdid).singleResult();
//        BpmnModel bpmnModel = repositoryService.getBpmnModel(definition.getId());
//        ObjectNode objectNode = new BpmnJsonConverter().convertToJson(bpmnModel);
//        Model modelData = repositoryService.newModel();
//        modelData.setKey(definition.getKey());
//        modelData.setName(definition.getName());
//        modelData.setCategory(definition.getCategory());
//        ObjectNode modelJson = new ObjectMapper().createObjectNode();
//        modelJson.put(ModelDataJsonConstants.MODEL_NAME, definition.getName());
//        modelJson.put(ModelDataJsonConstants.MODEL_DESCRIPTION, definition.getDescription());
//        List<Model> models = repositoryService.createModelQuery().modelKey(definition.getKey()).list();
//        if (models.size() > 0) {
//            Integer version = models.get(0).getVersion();
//            version++;
//            modelJson.put(ModelDataJsonConstants.MODEL_REVISION, version);
//            // 删除旧模型
//            repositoryService.deleteModel(models.get(0).getId());
//            modelData.setVersion(version);
//        } else {
//            modelJson.put(ModelDataJsonConstants.MODEL_REVISION, 1);
//        }
//        modelData.setMetaInfo(modelJson.toString());
//        modelData.setDeploymentId(definition.getDeploymentId());
//        // 保存新模型
//        repositoryService.saveModel(modelData);
//        // 保存模型json
//        repositoryService.addModelEditorSource(modelData.getId(), objectNode.toString().getBytes(StandardCharsets.UTF_8));
//        return objectNode.toString();
//    }

    //    @ApiOperation("挂起一个流程定义")
    @RequestMapping(value = "/suspendProcessDefinition", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult suspendProcessDefinition(@RequestParam("pdid") String pdid, @RequestParam("flag") Boolean flag,
                                               @RequestParam(value="date") String date) throws Exception {
        if (StringUtils.isNotEmpty(date)) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            repositoryService.suspendProcessDefinitionById(pdid, flag,  sdf.parse(date));
        } else {
            repositoryService.suspendProcessDefinitionById(pdid, flag, null);
        }

        return AjaxResult.success();
    }

    //    @ApiOperation("激活一个流程定义")
    @RequestMapping(value = "/activateProcessDefinition", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult activateProcessDefinition(@RequestParam("pdid") String pdid, @RequestParam("flag") Boolean flag, @RequestParam(value="date") String date) throws Exception {
        if (StringUtils.isNotEmpty(date)) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            repositoryService.activateProcessDefinitionById(pdid, flag,  sdf.parse(date));
        } else {
            repositoryService.activateProcessDefinitionById(pdid, flag, null);
        }
        return AjaxResult.success();
    }

    @RequestMapping(value = "/startBiShow", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult startBiShow() throws Exception {
        runtimeService.startProcessInstanceByKey("bi-show" , "1");
        return AjaxResult.success();
    }

    @ApiOperation("开始流程")
    @RequestMapping(value = "/start", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult start(@RequestParam("businessId")@ApiParam(value = "业务数据ID") Long businessId,
                            @RequestParam("businessKey")@ApiParam(value = "业务标识") String businessKey) throws Exception {
        String processInstanceId = flowServiceImpl.start(businessId, businessKey);
        return AjaxResult.success(processInstanceId);
    }

//    @ApiOperation("同意")
//    @RequestMapping(value = "/pass", method = RequestMethod.GET)
//    @ResponseBody
//    public AjaxResult pass(@RequestParam("pdid") String pdid) throws Exception {
////        flowServiceImpl.pass(getSysUser());
//        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        TaskService taskService = processEngine.getTaskService();
//        Long userId = getUserId();
//        HashMap<String, Object> vars = new HashMap<>();
////        Task task = taskService.createTaskQuery().processInstanceId(pdid).singleResult();
//        Task task = taskService.createTaskQuery().taskAssignee(userId.toString()).singleResult();
//        List<UserTask> nextTaskNode = this.getNextTaskNode(task.getId(), null);
//        if(!CollectionUtils.isEmpty(nextTaskNode)){
//            UserTask userTask = nextTaskNode.get(0);
//            String documentation = userTask.getDocumentation();
//            if(StringUtils.isNotBlank(documentation)){
//                List<String> userList = new ArrayList<>();
//                String[] split = documentation.split(",");
//                Collections.addAll(userList, split);
//                vars.put("userList", userList);
//            }
//            taskService.complete(task.getId(), vars);
////        taskService.complete(task.getId());
//        }
//
//        return AjaxResult.success();
//    }

    @ApiOperation("同意")
    @RequestMapping(value = "/pass", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult pass(@RequestBody FlowApproveDto flowApproveDto) throws Exception {
        flowServiceImpl.pass(flowApproveDto);

        return AjaxResult.success();
    }

    @ApiOperation("驳回")
    @RequestMapping(value = "/reject", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult endProcess(@RequestBody FlowApproveDto flowApproveDto) {
        try {
            flowServiceImpl.endProcess(flowApproveDto);
            return AjaxResult.success("流程审核驳回成功。");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("流程审核驳回失败，"+e.getMessage());
        }
    }

    @ApiOperation("撤回")
    @RequestMapping(value = "/withdraw", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult withdraw(@RequestParam("businessId")@ApiParam(value = "业务数据ID") Long businessId) {
        try {
            flowServiceImpl.withdraw(businessId);
            return AjaxResult.success("流程审核撤回成功。");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("流程审核撤回失败，"+e.getMessage());
        }
    }

    //    @ApiOperation("查看流程图")
    @RequestMapping(value = "/getPictiue", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult getPictiue(@ApiParam(value = "流程实例ID")@RequestParam("pdid") String pdid, @RequestParam("flowId") @ApiParam(value = "流程模型ID")String flowId) throws Exception {
        flowServiceImpl.getPictiue(pdid, flowId);

        return AjaxResult.success();
    }

    @ApiOperation("查看流程图")
    @RequestMapping(value = "/getProcessInstanceImage", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult getProcessInstanceImage(@ApiParam(value = "流程实例ID")@RequestParam("flowId") String flowId) throws Exception {
        byte[] image = flowServiceImpl.getProcessInstanceImage(flowId);
        return AjaxResult.success(image);
    }

    @ApiOperation("获取下一节点")
    @RequestMapping(value = "/nextNode", method = RequestMethod.GET)
    @ResponseBody
    public List<UserTask> getNextTaskNode(@ApiParam(value = "流程节点ID")@RequestParam("taskId") String taskId, @ApiParam(value = "拓展参数")Integer outcome) {
        return flowServiceImpl.getNextTaskNode(taskId, outcome);
    }

    @ApiOperation("获取下一节点")
    @RequestMapping(value = "/nextNodeByActivityId", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult<List<UserTask>> getNextTaskNodeByActivityId(
            @ApiParam(value = "流程实例ID")@RequestParam("flowId") String flowId) throws ServerException {
        return AjaxResult.success(flowServiceImpl.getNextTaskNodeByActivityId(flowId));
    }

    @ApiOperation("获取当前节点")
    @RequestMapping(value = "/currentNodeByFlowId", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult<UserTask> currentNodeByFlowId(
            @ApiParam(value = "流程实例ID")@RequestParam("flowId") String flowId) throws ServerException {
        return AjaxResult.success(flowServiceImpl.currentNodeByFlowId(flowId));
    }

    @ApiOperation("获取历史节点")
    @RequestMapping(value = "/history", method = RequestMethod.GET)
    @ResponseBody
    public List<HistoricTaskInstance> listHistoryTaskNodes(@ApiParam(value = "流程实例ID")@RequestParam("pdid") String pdid) {
        List<HistoricTaskInstance>  tasks =  historyService.createHistoricTaskInstanceQuery().processInstanceId(pdid).orderByHistoricTaskInstanceStartTime().asc().list();
        if(!CollectionUtils.isEmpty(tasks)) {
            List<HistoricTaskInstance> result = new ArrayList<>(tasks.size());
            for (HistoricTaskInstance task : tasks) {
                result.add(task);
            }
            return result;
        }
        return null;
    }

}
